home *** CD-ROM | disk | FTP | other *** search
/ Aminet 52 / Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso / Aminet / dev / gg / ncurses-5.3.lha / ncurses-5.3 / form / fty_enum.c < prev    next >
C/C++ Source or Header  |  2002-10-24  |  9KB  |  297 lines

  1.  
  2. /*
  3.  * THIS CODE IS SPECIFICALLY EXEMPTED FROM THE NCURSES PACKAGE COPYRIGHT.
  4.  * You may freely copy it for use as a template for your own field types.
  5.  * If you develop a field type that might be of general use, please send
  6.  * it back to the ncurses maintainers for inclusion in the next version.
  7.  */
  8. /***************************************************************************
  9. *                                                                          *
  10. *  Author : Juergen Pfeifer                                                *
  11. *  Contact: http://www.familiepfeifer.de/Contact.aspx?Lang=en              *
  12. *                                                                          *
  13. ***************************************************************************/
  14.  
  15. #include "form.priv.h"
  16.  
  17. MODULE_ID("$Id: fty_enum.c,v 1.16 2002/07/13 11:35:08 juergen Exp $")
  18.  
  19. typedef struct {
  20.   char **kwds;
  21.   int  count;
  22.   bool checkcase;
  23.   bool checkunique;
  24. } enumARG;
  25.  
  26. /*---------------------------------------------------------------------------
  27. |   Facility      :  libnform  
  28. |   Function      :  static void *Make_Enum_Type( va_list * ap )
  29. |   
  30. |   Description   :  Allocate structure for enumeration type argument.
  31. |
  32. |   Return Values :  Pointer to argument structure or NULL on error
  33. +--------------------------------------------------------------------------*/
  34. static void *Make_Enum_Type(va_list * ap)
  35. {
  36.   enumARG *argp = (enumARG *)malloc(sizeof(enumARG));
  37.  
  38.   if (argp)
  39.     {
  40.       int cnt = 0;
  41.       char **kp = (char **)0;
  42.       int ccase, cunique;
  43.  
  44.       argp->kwds        = va_arg(*ap,char **);
  45.       ccase             = va_arg(*ap,int);
  46.       cunique           = va_arg(*ap,int);
  47.       argp->checkcase   = ccase   ? TRUE : FALSE;
  48.       argp->checkunique = cunique ? TRUE : FALSE;
  49.  
  50.       kp = argp->kwds;
  51.       while( kp && (*kp++) ) cnt++;
  52.       argp->count = cnt;
  53.     }
  54.   return (void *)argp;
  55. }
  56.  
  57. /*---------------------------------------------------------------------------
  58. |   Facility      :  libnform  
  59. |   Function      :  static void *Copy_Enum_Type( const void * argp )
  60. |   
  61. |   Description   :  Copy structure for enumeration type argument.  
  62. |
  63. |   Return Values :  Pointer to argument structure or NULL on error.
  64. +--------------------------------------------------------------------------*/
  65. static void *Copy_Enum_Type(const void * argp)
  66. {
  67.   enumARG *result = (enumARG *)0;
  68.  
  69.   if (argp)
  70.     {
  71.       const enumARG *ap = (const enumARG *)argp;
  72.  
  73.       result = (enumARG *)malloc(sizeof(enumARG));
  74.       if (result)
  75.     *result = *ap;
  76.     }
  77.   return (void *)result;
  78. }
  79.  
  80. /*---------------------------------------------------------------------------
  81. |   Facility      :  libnform  
  82. |   Function      :  static void Free_Enum_Type( void * argp )
  83. |   
  84. |   Description   :  Free structure for enumeration type argument.
  85. |
  86. |   Return Values :  -
  87. +--------------------------------------------------------------------------*/
  88. static void Free_Enum_Type(void * argp)
  89. {
  90.   if (argp) 
  91.     free(argp);
  92. }
  93.  
  94. #define SKIP_SPACE(x) while(((*(x))!='\0') && (is_blank(*(x)))) (x)++
  95. #define NOMATCH 0
  96. #define PARTIAL 1
  97. #define EXACT   2
  98.  
  99. /*---------------------------------------------------------------------------
  100. |   Facility      :  libnform  
  101. |   Function      :  static int Compare(const unsigned char * s,  
  102. |                                       const unsigned char * buf,
  103. |                                       bool  ccase )
  104. |   
  105. |   Description   :  Check wether or not the text in 'buf' matches the
  106. |                    text in 's', at least partial.
  107. |
  108. |   Return Values :  NOMATCH   - buffer doesn't match
  109. |                    PARTIAL   - buffer matches partially
  110. |                    EXACT     - buffer matches exactly
  111. +--------------------------------------------------------------------------*/
  112. static int Compare(const unsigned char *s, const unsigned char *buf, 
  113.            bool ccase)
  114. {
  115.   SKIP_SPACE(buf); /* Skip leading spaces in both texts */
  116.   SKIP_SPACE(s);
  117.  
  118.   if (*buf=='\0')
  119.     {
  120.       return (((*s)!='\0') ? NOMATCH : EXACT);
  121.     } 
  122.   else 
  123.     {
  124.       if (ccase)
  125.     {
  126.       while(*s++ == *buf)
  127.         {
  128.           if (*buf++=='\0') return EXACT;
  129.         } 
  130.     } 
  131.       else 
  132.     {
  133.       while(toupper(*s++)==toupper(*buf))
  134.         {
  135.           if (*buf++=='\0') return EXACT;
  136.         }
  137.     }
  138.     }
  139.   /* At this location buf points to the first character where it no longer
  140.      matches with s. So if only blanks are following, we have a partial
  141.      match otherwise there is no match */
  142.   SKIP_SPACE(buf);
  143.   if (*buf) 
  144.     return NOMATCH;
  145.  
  146.   /* If it happens that the reference buffer is at its end, the partial
  147.      match is actually an exact match. */
  148.   return ((s[-1]!='\0') ? PARTIAL : EXACT);
  149. }
  150.  
  151. /*---------------------------------------------------------------------------
  152. |   Facility      :  libnform  
  153. |   Function      :  static bool Check_Enum_Field(
  154. |                                      FIELD * field,
  155. |                                      const void  * argp)
  156. |   
  157. |   Description   :  Validate buffer content to be a valid enumeration value
  158. |
  159. |   Return Values :  TRUE  - field is valid
  160. |                    FALSE - field is invalid
  161. +--------------------------------------------------------------------------*/
  162. static bool Check_Enum_Field(FIELD * field, const void  * argp)
  163. {
  164.   char **kwds       = ((const enumARG *)argp)->kwds;
  165.   bool ccase        = ((const enumARG *)argp)->checkcase;
  166.   bool unique       = ((const enumARG *)argp)->checkunique;
  167.   unsigned char *bp = (unsigned char *)field_buffer(field,0);
  168.   char *s, *t, *p;
  169.   int res;
  170.   
  171.   while( kwds && (s=(*kwds++)) )
  172.     {
  173.       if ((res=Compare((unsigned char *)s,bp,ccase))!=NOMATCH)
  174.     {
  175.       p=t=s; /* t is at least a partial match */
  176.       if ((unique && res!=EXACT)) 
  177.         {
  178.           while( kwds && (p = *kwds++) )
  179.         {
  180.           if ((res=Compare((unsigned char *)p,bp,ccase))!=NOMATCH)
  181.             {
  182.               if (res==EXACT)
  183.             {
  184.               t = p;
  185.               break;
  186.             }
  187.               else
  188.             t = (char *)0;
  189.             }
  190.         }
  191.         }      
  192.       if (t)
  193.         {
  194.           set_field_buffer(field,0,t);
  195.           return TRUE;
  196.         }
  197.       if (!p)
  198.         break;
  199.     }
  200.     }
  201.   return FALSE;
  202. }
  203.  
  204. static const char *dummy[] = { (char *)0 };
  205.  
  206. /*---------------------------------------------------------------------------
  207. |   Facility      :  libnform  
  208. |   Function      :  static bool Next_Enum(FIELD * field,
  209. |                                          const void * argp)
  210. |   
  211. |   Description   :  Check for the next enumeration value
  212. |
  213. |   Return Values :  TRUE  - next value found and loaded
  214. |                    FALSE - no next value loaded
  215. +--------------------------------------------------------------------------*/
  216. static bool Next_Enum(FIELD * field, const void * argp)
  217. {
  218.   const enumARG *args = (const enumARG *)argp;
  219.   char **kwds       = args->kwds;
  220.   bool ccase        = args->checkcase;
  221.   int cnt           = args->count;
  222.   unsigned char *bp = (unsigned char *)field_buffer(field,0);
  223.  
  224.   if (kwds) {
  225.     while(cnt--)
  226.       {
  227.     if (Compare((unsigned char *)(*kwds++),bp,ccase)==EXACT) 
  228.       break;
  229.       }
  230.     if (cnt<=0)
  231.       kwds = args->kwds;
  232.     if ((cnt>=0) || (Compare((const unsigned char *)dummy,bp,ccase)==EXACT))
  233.       {
  234.     set_field_buffer(field,0,*kwds);
  235.     return TRUE;
  236.       }
  237.   }
  238.   return FALSE;
  239. }
  240.  
  241. /*---------------------------------------------------------------------------
  242. |   Facility      :  libnform  
  243. |   Function      :  static bool Previous_Enum(
  244. |                                          FIELD * field,
  245. |                                          const void * argp)
  246. |   
  247. |   Description   :  Check for the previous enumeration value
  248. |
  249. |   Return Values :  TRUE  - previous value found and loaded
  250. |                    FALSE - no previous value loaded
  251. +--------------------------------------------------------------------------*/
  252. static bool Previous_Enum(FIELD * field, const void * argp)
  253. {
  254.   const enumARG *args = (const enumARG *)argp;
  255.   int cnt       = args->count;
  256.   char **kwds   = &args->kwds[cnt-1];
  257.   bool ccase    = args->checkcase;
  258.   unsigned char *bp = (unsigned char *)field_buffer(field,0);
  259.  
  260.   if (kwds) {
  261.     while(cnt--)
  262.       {
  263.     if (Compare((unsigned char *)(*kwds--),bp,ccase)==EXACT) 
  264.       break;
  265.       }
  266.     
  267.     if (cnt<=0)
  268.       kwds  = &args->kwds[args->count-1];
  269.     
  270.     if ((cnt>=0) || (Compare((const unsigned char *)dummy,bp,ccase)==EXACT))
  271.       {
  272.     set_field_buffer(field,0,*kwds);
  273.     return TRUE;
  274.       }
  275.   }
  276.   return FALSE;
  277. }
  278.  
  279.  
  280. static FIELDTYPE typeENUM = {
  281.   _HAS_ARGS | _HAS_CHOICE | _RESIDENT,
  282.   1,                           /* this is mutable, so we can't be const */
  283.   (FIELDTYPE *)0,
  284.   (FIELDTYPE *)0,
  285.   Make_Enum_Type,
  286.   Copy_Enum_Type,
  287.   Free_Enum_Type,
  288.   Check_Enum_Field,
  289.   NULL,
  290.   Next_Enum,
  291.   Previous_Enum
  292. };
  293.  
  294. NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_ENUM = &typeENUM;
  295.  
  296. /* fty_enum.c ends here */
  297.